package de.imdb250junkie.gui;

import java.awt.Container;
import java.awt.Desktop;
import java.awt.DisplayMode;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ResourceBundle;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;

import de.imdb250junkie.db.DB;
import de.imdb250junkie.locale.LocaleUtils;
import de.imdb250junkie.utils.Loader;
import de.imdb250junkie.utils.Movie;
import de.imdb250junkie.utils.State;

/**
 * @author André Stannek
 * @version 2010-02-10
 */
public class MainWindow extends JFrame implements ActionListener
{
    /**
     * 
     */
    private static final long serialVersionUID = 2740437090361841747L;

    /**
     * 
     */
    private final transient Movie[] top250;

    /**
     * 
     */
    private transient JList<Movie> movieList;

    /**
     * 
     */
    private transient JButton updateButton, seenButton, unseenButton,
            boughtButton, linkButton, resetButton, saveButton, loadButton,
            languageButton;

    /**
     * 
     */
    private final transient DB database;

    /**
     * 
     */
    private final transient Stats stats;

    /**
     * Localization ressource
     */
    private final transient ResourceBundle locale;

    /**
     * @param database
     *            the Database that will be represented
     */
    public MainWindow(final DB database)
    {
        super("imdb250junkie");
        this.database = database;
        database.save();
        top250 = database.getTop();
        stats = new Stats(top250);
        locale = ResourceBundle.getBundle("de.imdb250junkie.locale.GUIStrings",
                LocaleUtils.getLocale());
        initUI();
    }

    /**
     * Initiats the UI Components.
     */
    private void initUI()
    {
        final int width = 610;
        final int heigth = 700;
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        final Container contentPane = new Container();
        contentPane.setLayout(new GridBagLayout());
        final GridBagConstraints constraint = new GridBagConstraints();
        constraint.fill = GridBagConstraints.HORIZONTAL;
        constraint.anchor = GridBagConstraints.LINE_START;

        constraint.gridx = 0;
        constraint.gridy = 0;
        constraint.weightx = 0.1;
        constraint.gridheight = 4;
        contentPane.add(stats);
        constraint.gridx = 0;
        constraint.gridy = 4;
        constraint.gridheight = 2;
        boughtButton = new JButton(locale.getString("bought_button"));
        boughtButton.addActionListener(this);
        contentPane.add(boughtButton, constraint);
        constraint.gridy = 6;
        seenButton = new JButton(locale.getString("seen_button"));
        seenButton.addActionListener(this);
        contentPane.add(seenButton, constraint);
        constraint.gridy = 8;
        unseenButton = new JButton(locale.getString("not_seen_button"));
        unseenButton.addActionListener(this);
        contentPane.add(unseenButton, constraint);
        constraint.gridy = 10;
        linkButton = new JButton(locale.getString("info_button"));
        linkButton.addActionListener(this);
        contentPane.add(linkButton, constraint);
        constraint.gridy = 12;
        updateButton = new JButton(locale.getString("update_button"));
        updateButton.addActionListener(this);
        contentPane.add(updateButton, constraint);
        constraint.gridy = 14;
        saveButton = new JButton(locale.getString("export_button"));
        saveButton.addActionListener(this);
        contentPane.add(saveButton, constraint);
        constraint.gridy = 16;
        loadButton = new JButton(locale.getString("import_button"));
        loadButton.addActionListener(this);
        contentPane.add(loadButton, constraint);
        constraint.gridy = 18;
        resetButton = new JButton(locale.getString("reset_button"));
        resetButton.addActionListener(this);
        contentPane.add(resetButton, constraint);
        constraint.gridy = 20;
        languageButton = new JButton(locale.getString("select_language"));
        languageButton.addActionListener(this);
        contentPane.add(languageButton, constraint);

        final DefaultListModel<Movie> listModel = new DefaultListModel<>();
        for (int i = 0; i < top250.length; i++)
        {
            listModel.add(i, top250[i]);
        }
        movieList = new JList<>();
        movieList.setCellRenderer(new ListElement());
        movieList.setModel(listModel);
        movieList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        final JScrollPane scroller = new JScrollPane(movieList);
        scroller.setSize(400 + scroller.getVerticalScrollBar().getWidth(),
                heigth);
        constraint.gridx = 1;
        constraint.gridy = 0;
        constraint.weightx = 0.9;
        constraint.gridheight = 21;
        constraint.ipady = heigth - 70;
        constraint.ipadx = 400 + scroller.getVerticalScrollBar().getWidth();
        contentPane.add(scroller, constraint);

        this.setContentPane(contentPane);
        final DisplayMode displayMode = GraphicsEnvironment
                .getLocalGraphicsEnvironment().getDefaultScreenDevice()
                .getDisplayMode();
        this.setBounds((displayMode.getWidth() - width) / 2,
                (displayMode.getHeight() - heigth) / 2, width, heigth);
        this.setVisible(true);

    }

    @Override
    public final void actionPerformed(final ActionEvent event)
    {
        if (event.getSource().equals(updateButton))
        {
            new UpdateWindow(database, new UpdateDoneListener()
            {
                @Override
                public void done()
                {
                    new MainWindow(database);
                }
            });
            this.dispose();
        }
        else if (event.getSource().equals(saveButton))
        {
            save();
        }
        else if (event.getSource().equals(loadButton))
        {
            load();
        }
        else if (event.getSource().equals(resetButton))
        {
            reset();
        }
        else if (event.getSource() == (languageButton))
        {
            new LanguageSelector(this);
        }
        else
        {
            final Object object = movieList.getSelectedValue();
            if (object instanceof Movie)
            {
                final Movie movie = (Movie) object;
                if (event.getSource() == (unseenButton))
                {
                    markUnseen(movie);
                }
                else if (event.getSource() == (seenButton))
                {
                    markSeen(movie);
                }
                else if (event.getSource() == (boughtButton))
                {
                    markBought(movie);
                }
                else if (event.getSource() == (linkButton))
                {
                    try
                    {
                        Desktop.getDesktop().browse(movie.getLink().toURI());
                    }
                    catch (final IOException e)
                    {
                        JOptionPane.showMessageDialog(this,
                                locale.getString("webpage_open"), "IO-Error",
                                JOptionPane.ERROR_MESSAGE);
                    }
                    catch (final URISyntaxException e)
                    {
                        JOptionPane.showMessageDialog(this,
                                locale.getString("url_syntax"),
                                "URl-Syntax-Error", JOptionPane.ERROR_MESSAGE);
                    }
                }
            }
        }

    }

    /**
     * @param movie
     *            the movie
     */
    private void markSeen(final Movie movie)
    {
        movie.setState(State.SEEN);
        database.save();
        movieList.repaint();
        stats.update();
    }

    /**
     * @param movie
     *            the movie
     */
    private void markUnseen(final Movie movie)
    {
        movie.setState(State.UNSEEN);
        database.save();
        movieList.repaint();
        stats.update();
    }

    /**
     * @param movie
     *            the movie
     */
    private void markBought(final Movie movie)
    {
        movie.setState(State.BOUGHT);
        database.save();
        movieList.repaint();
        stats.update();
    }

    /**
     * marks all movies in the database unseen.
     */
    private void reset()
    {
        for (final Movie m : database)
        {
            m.setState(State.UNSEEN);
        }
        database.save();
        movieList.repaint();
        stats.update();
    }

    /**
     * 
     */
    private void load()
    {
        final JFileChooser fileChooser = new JFileChooser();
        final int returnVal = fileChooser.showOpenDialog(this);

        if (returnVal == JFileChooser.APPROVE_OPTION)
        {
            final File file = fileChooser.getSelectedFile();
            Loader.load(file.getAbsolutePath());
            this.dispose();
        }
    }

    /**
     * 
     */
    private void save()
    {
        final JFileChooser fileChooser = new JFileChooser();
        final int returnVal = fileChooser.showSaveDialog(this);

        if (returnVal == JFileChooser.APPROVE_OPTION)
        {
            final File file = fileChooser.getSelectedFile();
            database.save(file.getAbsolutePath());
        }
    }
}
